package myJs.user.soft.preprocess

import myJs.Implicits.FieldValue
import myJs.api.Api
import myJs.myPkg.yup.{ConditionOptions, Yup}
import myJs.tool.Tool.messages

import scala.scalajs.js
import org.scalajs.macrotaskexecutor.MacrotaskExecutor.Implicits._

import scala.concurrent.Future
import scala.scalajs.js.JSConverters._
import scala.collection.mutable
import myJs.Implicits._

/**
 * Created by yz on 9/11/2022
 */
object Schema {

  case class ValidInfo(v: String, valid: Boolean)

  val curTool = Preprocess
  val cacheMap = mutable.SeqMap[String, ValidInfo]()

  def cacheTest(key: String)(f: String => Future[Boolean]) = (v: String) => {
    val beforeV = cacheMap.getOrElse(key, ValidInfo("", true))
    if (beforeV.v != v) {
      f(v).map { x =>
        cacheMap.put(key, ValidInfo(v, x))
        x
      }.toJSPromise
    } else {
      Future {
        beforeV.valid
      }.toJSPromise
    }
  }

  def missionNameValidateF(key: String) = cacheTest(key) { v: String =>
    import shared.pojo.Pojo.workflowMission._
    val request = MissionNameCheck.Request(id = curTool.getId, missionName = v)
    Api.workflowMission.missionNameCheck(request).map { response =>
      response.valid
    }
  }

  def fileValidateF(key: String) = cacheTest(key) { v: String =>
    import shared.pojo.Pojo.soft._
    val request = CheckFileName.Request(id = curTool.getId, fileName = v)
    Api.soft.checkFileName(request).map { response =>
      response.valid
    }
  }


  def transformF = (v: Double) => {
    if (v.isNaN) {
      js.undefined
    } else js.defined(v)
  }

  val schema = Yup.`object`().shape(js.Dictionary(
    "missionName" -> Yup.string().required(messages("null")).
      test(name = "checkExist", message = messages("exist"), test = missionNameValidateF("missionName")),
    "file" -> Yup.string().required(messages("null")).
      test(name = "checkNotExist", message = s"${messages("notExist")}", test = fileValidateF("file")),
    "groupFile" -> Yup.string().when("hasGroup", ConditionOptions(
      is = true,
      `then` = Yup.string().required(message = s"${messages("null")}")
        .test(name = "checkNotExist", message = s"${messages("notExist")}", test = fileValidateF("groupFile")),
      otherwise = Yup.string()
    )),
    "datas" -> Yup.array().of(
      Yup.`object`().shape(
        js.Dictionary(
          "colNaRate" -> Yup.number().required(message = s"${messages("null")}")
            .typeError(message = s"${messages("numeric")}")
            .min(min = 0, message = s"${messages("between", 0, 100)}")
            .max(max = 100, message = s"${messages("between", 0, 100)}"),
          "rowNaRate" -> Yup.number().required(message = s"${messages("null")}")
            .typeError(message = s"${messages("numeric")}")
            .min(min = 0, message = s"${messages("between", 0, 100)}")
            .max(max = 100, message = s"${messages("between", 0, 100)}"),
          "rsd" -> Yup.number().required(message = s"${messages("null")}")
            .typeError(message = s"${messages("numeric")}")
            .min(min = 0, message = s"${messages("between", 0, 100)}")
            .max(max = 100, message = s"${messages("between", 0, 100)}"),
          "knnShow" -> Yup.boolean(),
          "knn" -> Yup.number().when("knnShow", ConditionOptions(
            is = true,
            `then` = Yup.number().required(message = s"${messages("null")}")
              .typeError(message = s"${messages("numeric")}")
              .integer(message = s"${messages("integer")}")
              .moreThan(more = 0, message = s"${messages("greaterThan", 0)}"),
            otherwise = Yup.number().nullable(true).transform(transformF)
          )),
          "minShow" -> Yup.boolean(),
          "min" -> Yup.number().when("minShow", ConditionOptions(
            is = true,
            `then` = Yup.number().required(message = s"${messages("null")}")
              .typeError(message = s"${messages("numeric")}")
              .integer(message = s"${messages("integer")}")
              .moreThan(more = 0, message = s"${messages("greaterThan", 0)}"),
            otherwise = Yup.number().nullable(true).transform(transformF)
          )),
          "glogShow" -> Yup.boolean(),
          "glog" -> Yup.number().when("glogShow", ConditionOptions(
            is = true,
            `then` = Yup.number().required(message = s"${messages("null")}")
              .typeError(message = s"${messages("numeric")}"),
            otherwise = Yup.number().nullable(true).transform(transformF)
          )),
          "constantShow" -> Yup.boolean(),
          "constant" -> Yup.number().when("constantShow", ConditionOptions(
            is = true,
            `then` = Yup.number().required(message = s"${messages("null")}")
              .typeError(message = s"${messages("numeric")}"),
            otherwise = Yup.number().nullable(true).transform(transformF)
          )),
          "topNShow" -> Yup.boolean(),
          "topN" -> Yup.number().when("topNShow", ConditionOptions(
            is = true,
            `then` = Yup.number().required(message = s"${messages("null")}")
              .typeError(message = s"${messages("numeric")}")
              .integer(message = s"${messages("integer")}")
              .moreThan(more = 0, message = s"${messages("greaterThan", 0)}"),
            otherwise = Yup.number().nullable(true).transform(transformF)
          )),
          "topPercentShow" -> Yup.boolean(),
          "topPercent" -> Yup.number().when("topPercentShow", ConditionOptions(
            is = true,
            `then` = Yup.number().required(message = s"${messages("null")}")
              .typeError(message = s"${messages("numeric")}")
              .moreThan(more = 0, message = s"${messages("greaterThan", 0)}"),
            otherwise = Yup.number().nullable(true).transform(transformF)
          )),
          "removeGroups" -> Yup.array().min(1, s"${messages("null")}").of(
            Yup.`object`().shape(js.Dictionary(
              "label" -> Yup.string(),
              "value" -> Yup.string(),
            )).nullable()
          ),
        )
      )
    ),
  ))


}
